package com.idanchuang.component.businesslog.es.annotations;

import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.AcknowledgedResponse;
import org.elasticsearch.client.indexlifecycle.*;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * The XpackIndexLifeCycle
 *
 * @since 2020/7/16
 */
public class XPackIndexLifeCycle implements IndexLifeCycle {

    private static final Logger log = LoggerFactory.getLogger(XPackIndexLifeCycle.class);

    private RestHighLevelClient client;

    public XPackIndexLifeCycle(RestHighLevelClient restHighLevelClient) {
        this.client = restHighLevelClient;
    }

    @Override
    public String findIlmPolicy(Document document) throws IOException {
        String rollMode = document.rollMode().toString();
        String maxAge = document.maxDays() <= 0 ? "0d" : document.maxDays() + "d";

        // 不执行策略
        if (document.rollMode() == RollMode.NONE && document.maxDays() <= 0) {
            return null;
        }
        // 执行策略
        String policyName = ("policy_ro_" + rollMode + "_del_" + maxAge).toLowerCase();
        GetLifecyclePolicyRequest request = new GetLifecyclePolicyRequest(policyName);
        try {
            client.indexLifecycle().getLifecyclePolicy(request, RequestOptions.DEFAULT);
        } catch (ElasticsearchStatusException e) {
            if (e.getMessage().contains("resource_not_found_exception")) {
                Map<String, Phase> map = new HashMap<>();

                TimeValue timeValue;
                switch (document.rollMode()) {
                    case MINUTE:
                        timeValue = TimeValue.parseTimeValue("1m", "1m");
                        break;
                    case HOUR:
                        timeValue = TimeValue.parseTimeValue("1h", "1h");
                        break;
                    case DAY:
                        timeValue = TimeValue.parseTimeValue("1d", "1d");
                        break;
                    case WEEK:
                        timeValue = TimeValue.parseTimeValue("7d", "7d");
                        break;
                    case MONTH:
                        timeValue = TimeValue.parseTimeValue("30d", "30d");
                        break;
                    case YEAR:
                        timeValue = TimeValue.parseTimeValue("365d", "365d");
                        break;
                    default:
                        timeValue = null;
                        break;
                }
                if (timeValue != null) {
                    Map<String, LifecycleAction> lifecycleActionMap1 = new HashMap<>();
                    LifecycleAction rollover = new RolloverAction(null, timeValue, null);
                    lifecycleActionMap1.put("rollover", rollover);
                    map.put("hot", new Phase("hot", null, lifecycleActionMap1));
                }
                if (document.maxDays() > 0) {
                    Map<String, LifecycleAction> lifecycleActionMap2 = new HashMap<>();
                    LifecycleAction delete = new DeleteAction();
                    lifecycleActionMap2.put("delete", delete);
                    map.put("delete", new Phase("delete", TimeValue.parseTimeValue(maxAge, maxAge), lifecycleActionMap2));
                }
                LifecyclePolicy lifecyclePolicy = new LifecyclePolicy(policyName, map);
                PutLifecyclePolicyRequest putRequest = new PutLifecyclePolicyRequest(lifecyclePolicy);
                AcknowledgedResponse response = client.indexLifecycle().putLifecyclePolicy(putRequest, RequestOptions.DEFAULT);
                boolean acknowledged = response.isAcknowledged();
                if (acknowledged) {
                    log.info("create lifecyclePolicy {}", policyName);
                }
            }
        }
        return policyName;
    }

    @Override
    public void checkTemplate(String indexName, String policyName) throws IOException {
        String templateName = indexName + "_template";
        IndexTemplatesExistRequest request = new IndexTemplatesExistRequest(templateName);
        boolean exists = client.indices().existsTemplate(request, RequestOptions.DEFAULT);
        if (!exists) {
            PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest(templateName);
            Map<String, Object> settings = new HashMap<>();
            settings.put("number_of_shards", 1);
            settings.put("number_of_replicas", 1);
            settings.put("index.lifecycle.name", policyName);
            settings.put("index.lifecycle.rollover_alias", indexName);
            putRequest.settings(settings);
            putRequest.patterns(Collections.singletonList(indexName + "-*"));
            org.elasticsearch.action.support.master.AcknowledgedResponse response = client.indices()
                    .putTemplate(putRequest, RequestOptions.DEFAULT);
            boolean acknowledged = response.isAcknowledged();
            if (acknowledged) {
                log.info("create index template {}", templateName);
            }
        }
    }
}
